package session

import (
	authenticator "admin/contrib/google"
	"common/helper"
	"context"
	"encoding/json"
	"errors"
	"github.com/go-redis/redis/v8"
	"github.com/valyala/fasthttp"
	"net/url"
	"strconv"
	"time"
)

var (
	prefix string
	ctx    = context.Background()
	client *redis.Client
)

func New(reddb *redis.Client, p string) {

	client = reddb
	prefix = p
}

func AdminSet(loginuser string, id string, name string, password string) (string, error) {

	key := helper.MD5Hash(loginuser + id + strconv.FormatInt(time.Now().UnixMilli(), 10))
	value := map[string]string{
		"loginuser": loginuser,
		"id":        id,
		"name":      name,
		"password":  password,
	}
	jsonvalue, _ := json.Marshal(value)
	client.Set(ctx, key, jsonvalue, 24*30*time.Hour)
	client.Set(ctx, loginuser+":"+id, key, 24*30*time.Hour)
	return key, nil
}

func AdminClear(ctx *fasthttp.RequestCtx) (map[string]string, error) {
	key := string(ctx.Request.Header.Peek("t"))
	mapValue := make(map[string]string)
	if len(key) == 0 {
		key = string(ctx.QueryArgs().Peek("t"))
		if len(key) == 0 {
			return mapValue, errors.New("token error")
		}
	}

	value, err := client.Get(ctx, key).Result()
	if err != nil || value == "" {
		return mapValue, errors.New("token error")
	}

	json.Unmarshal([]byte(value), &mapValue)
	valueKey := client.Get(ctx, mapValue["loginuser"]+":"+mapValue["id"]).Val()
	if valueKey != key {
		//单点登录验证
		//return errors.New("token error")
	}
	client.Del(ctx, key)
	return mapValue, nil
}

func AdminCheck(ctx *fasthttp.RequestCtx) (map[string]string, error) {
	key := string(ctx.Request.Header.Peek("t"))
	mapValue := make(map[string]string)
	if len(key) == 0 {
		key = string(ctx.QueryArgs().Peek("t"))
		if len(key) == 0 {
			return mapValue, errors.New("token error")
		}
	}

	value, err := client.Get(ctx, key).Result()
	if err != nil || value == "" {
		return mapValue, errors.New("token error")
	}

	json.Unmarshal([]byte(value), &mapValue)
	valueKey := client.Get(ctx, mapValue["loginuser"]+":"+mapValue["id"]).Val()
	if valueKey != key {
		//单点登录验证
		//return errors.New("token error")
	}

	_ = client.ExpireAt(ctx, key, ctx.Time().Add(24*30*time.Hour))
	_ = client.ExpireAt(ctx, valueKey, ctx.Time().Add(24*30*time.Hour))
	return mapValue, nil
}

func AdminGet(ctx *fasthttp.RequestCtx) map[string]string {
	data := make(map[string]string)
	key := string(ctx.Request.Header.Peek("t"))
	if len(key) == 0 {
		key = string(ctx.QueryArgs().Peek("t"))
		if len(key) == 0 {
			return data
		}
	}
	value := client.Get(ctx, key).Val()
	json.Unmarshal([]byte(value), &data)
	return data
}

func AdminSetGoogleSecret(id string, name string) (string, string) {
	secret := authenticator.GetSecret()
	key := "admin:" + id + ":googleSecret"
	client.Set(ctx, key, secret, 24*time.Hour)
	encodedStr := url.QueryEscape("otpauth://totp/" + name + "?secret=" + secret)
	return secret, "https://api.qrserver.com/v1/create-qr-code/?data=" + encodedStr + "&size=200x200&ecc=M"
	//return secret
}

func AdminGetGoogleSecret(id string) string {
	key := "admin:" + id + ":googleSecret"
	secret := client.Get(ctx, key).Val()
	return secret
}

func MerchantSetGoogleSecret(id string, name string) (string, string) {
	secret := authenticator.GetSecret()
	key := "merchant:" + id + ":googleSecret"
	client.Set(ctx, key, secret, 24*time.Hour)
	encodedStr := url.QueryEscape("otpauth://totp/" + name + "?secret=" + secret)
	return secret, "https://api.qrserver.com/v1/create-qr-code/?data=" + encodedStr + "&size=200x200&ecc=M"
	//return secret
}

func MerchantGetGoogleSecret(id string) string {
	key := "merchant:" + id + ":googleSecret"
	secret := client.Get(ctx, key).Val()
	return secret
}

func BusinessSetGoogleSecret(id string, name string) (string, string) {
	secret := authenticator.GetSecret()
	key := "business:" + id + ":googleSecret"
	client.Set(ctx, key, secret, 24*time.Hour)
	encodedStr := url.QueryEscape("otpauth://totp/" + name + "?secret=" + secret)
	return secret, "https://api.qrserver.com/v1/create-qr-code/?data=" + encodedStr + "&size=200x200&ecc=M"
	//return secret
}

func BusinessGetGoogleSecret(id string) string {
	key := "business:" + id + ":googleSecret"
	secret := client.Get(ctx, key).Val()
	return secret
}
